package com.attilax.fsm;

import java.util.List;

import com.attilax.json.AtiJson;
import com.attilax.net.HttpUtil;
import com.google.common.collect.Lists;

/**
 * 单词流必须识别为保留字，标识符(变量)，常量，操作符(运算符 )和界符五大类
 * 常数就是一个数,常量是一个不能被改变的变量
 * @author Administrator
 *
 */
public class JavaTokener {
	//operators ()
	//keyword 
	//str
	//num
	List<Token> tokens = Lists.newArrayList();
	String curTokenTxt = "";
	String splitors = "(),";
	String curStat = "ini";
	private String code;
	public char[] code_char_arr;

	public JavaTokener(String code) {
		this.code = code.trim();
	}

	public List getTokensV4() {
		code_char_arr = code.toCharArray();
		for (char c : code_char_arr) {
			if(this.curTokenTxt.equals("1598"))
				System.out.println("dbg");
			// get next char,,then change stat
			// jude cur char and cur stat...then if or not chage stat
			if (c == '[' && !this.curStat.equals("strStart"))
			{
				this.curStat="sqBrkStart";
				Token tk2=new Token("[").setType("spltr");
				tokens.add(tk2);
				this.curTokenTxt = "";
				continue;
				
			}
				
		     if (c == ']' && !this.curStat.equals("strStart"))
		     {
		    	 this.curStat="sqBrkEnd";
					Token tk2=new Token("]").setType("spltr");
					tokens.add(tk2);
					this.curTokenTxt = "";
					continue;
		     }
			if(c==' ' && this.curStat.equals("ini"))
			{
				if(this.curTokenTxt.trim().toLowerCase().equals("new"))
				{
					this.curStat = "brkStart";
					Token tk=new Token(this.curTokenTxt).setType("keyword");				
					tokens.add(tk);
					this.curTokenTxt = "";
					continue;
				}
			
			}
			if (c == '(' && !this.curStat.equals("strStart")) {    //&&  cur stta=ini
				this.curStat = "brkStart";
				Token tk=new Token(this.curTokenTxt).setType("var");
				
				tokens.add(tk);
				
				Token tk2=new Token("(").setType("op");
				tokens.add(tk2);
				this.curTokenTxt = "";
				continue;
			}
//			if(c=='\\')
//			{
//				this.curStat = "splashStart";
//			}

//			if (c == '.' && this.curStat.equals("brkStart")) {
//
//				curToken = curToken + String.valueOf(c);
//				continue;
//
//				// this.curStat.equals("brkEnd"))
//
//			}
//			
			
			if (c == ')' && !this.curStat.equals("strStart")) { // && cur stat
																// =brk start

				if (this.curTokenTxt.length()> 0) //jeig cant smp...  last end brk is impt..if smp continue ,then cant add end brk to token
				{

					String type = gettype_4curCharIsBrkend(this.curTokenTxt, this.curStat);
					Token tk3 = new Token(this.curTokenTxt).setType(type);
					tokens.add(tk3);
				}

				Token tk2 = new Token(")").setType("op");
				tokens.add(tk2);
				this.curTokenTxt = "";
				this.curStat = "brkEnd";
				continue;
			}
			
			if (c == '.' && this.curStat.equals("brkEnd")) {
				 
				Token tk2=new Token(".").setType("op");
				tokens.add(tk2);
				curTokenTxt = "";
				continue;
			}
			
			//---------------str type 
			//&&   this.curStat.equals("brkStart")   mayube   []  arr hto..
			//first quoe
			if( (c=='\"'|| c=='\'')  &&   (this.curStat != "strStart"))   //
			{
				this.curStat = "strStart";
			//	tokens.add(c);
				this.curTokenTxt = "";
				continue;
			}
			
			//for close quoue
			if( (c=='\"'|| c=='\'') && this.curStat.equals("strStart"))
			{
				this.curStat = "strEnd";
				Token tk3=new Token(this.curTokenTxt).setType("str");
				tokens.add(tk3);
				this.curTokenTxt = "";
				continue;
			}
			//sec quoeo
//			if(  (c=='\"'|| c=='\'') && this.curStat.equals("commaStat"))
//			{
//				this.curStat = "strStart";
//			//	tokens.add(this.curToken);
//				this.curTokenTxt = "";
//				continue;
//			}
			if(c==':' && !this.curStat.equals("strStart"))
			{
				
				if(this.curTokenTxt.trim().length()>0)
			 	{  
						String curTokenTye="con";
						 
						Token tk4=new Token(this.curTokenTxt).setType(curTokenTye);
						tokens.add(tk4);
				 }
				
				Token tk3=new Token( String.valueOf(c)).setType("op");
				tokens.add(tk3);
				this.curTokenTxt = "";
				this.curStat = "colon";
				continue;
			 
			}
			
			
			if(c==',' && !this.curStat.equals("strStart"))
			{
				
				
				if(this.curTokenTxt.trim().length()>0)
			 	{  
						String curTokenTye="con";
						if(this.curTokenTxt.startsWith(":"))
							curTokenTye="op";
						else if(this.curStat.equals("colon"))
							curTokenTye="op";
						Token tk4=new Token(this.curTokenTxt).setType(curTokenTye);
						tokens.add(tk4);
				 }
				
				Token tk3=new Token( String.valueOf(c)).setType("spltr");
				tokens.add(tk3);
				this.curTokenTxt = "";
				this.curStat = "commaStat";
				continue;
			}
			
//			if(c==',' && this.curStat.equals("strEnd"))
//			{
//			//	tokens.add(","); 
//			 	this.curTokenTxt = "";
//				continue;
//			}
		//	if (this.curStat.equals("ini"))
				curTokenTxt = curTokenTxt + String.valueOf(c);
		}
		return tokens;
	}


	/**
	 * http://localhost/new(com.attilax.util.connReduceDync).set_resfile(uc_js.txt).joinNout()
	 * http://localhost/wrmiServlet?code=new(com.attilax.util.connReduceDync).set_resfile(uc_js.txt).joinNout()
	 * @param args
	 */
	public static void main(String[] args) {
		String code = "new com.attilax.util.connReduceDync().set_resfile(uc_js.txt).joinNout() "
				.trim();
		code="HttpUtil.down(\"http://www.winrar.com.cn/download/wrar540scp.exe\", \"c:\\0down.exe\")";
		List li = new JavaTokener(code).getTokensV2();
		System.out.println(AtiJson.toJson(li));

	}
//HttpUtil.down("http://www.winrar.com.cn/download/wrar540scp.exe", "c:\0down.exe")
	@Deprecated
	public List getTokens() {
		code_char_arr = code.toCharArray();
		for (char c : code_char_arr) {
			// get next char,,then change stat
			// jude cur char and cur stat...then if or not chage stat
			if(c==' ' && this.curStat.equals("ini"))
			{
				if(this.curTokenTxt.trim().toLowerCase().equals("new"))
				{
					this.curStat = "brkStart";
					Token tk=new Token(this.curTokenTxt).setType("keyword");				
					tokens.add(tk);
					this.curTokenTxt = "";
					continue;
				}
			
			}
			
			if (c == '(' && !this.curStat.equals("strStart")) {    //&&  cur stta=ini
				this.curStat = "brkStart";
				Token tk=new Token(this.curTokenTxt).setType("var");
				
				tokens.add(tk);
				
				Token tk2=new Token("(").setType("op");
				tokens.add(tk2);
				this.curTokenTxt = "";
				continue;
			}
//			if(c=='\\')
//			{
//				this.curStat = "splashStart";
//			}

//			if (c == '.' && this.curStat.equals("brkStart")) {
//
//				curToken = curToken + String.valueOf(c);
//				continue;
//
//				// this.curStat.equals("brkEnd"))
//
//			}
//			
			if (c == ')'  && !this.curStat.equals("strStart") ) {    //&& cur stat =brk start
				this.curStat = "brkEnd";
				if(this.curTokenTxt.length()>0)
				{
					Token tk3=new Token(this.curTokenTxt).setType("var");
					tokens.add(tk3);
				}
				
				Token tk2=new Token(")").setType("op");
				tokens.add(tk2);
				this.curTokenTxt = "";
				continue;
			}
			
			if (c == '.' && this.curStat.equals("brkEnd")) {
				 
				Token tk2=new Token(".").setType("var");
				tokens.add(tk2);
				curTokenTxt = "";
				continue;
			}
			
			//---------------str type 
			if(c=='\"' && this.curStat.equals("brkStart"))
			{
				this.curStat = "strStart";
			//	tokens.add(c);
				this.curTokenTxt = "";
				continue;
			}
			
			
			if(c=='\"' && this.curStat.equals("strStart"))
			{
				this.curStat = "strEnd";
				Token tk3=new Token(this.curTokenTxt).setType("str");
				tokens.add(tk3);
				this.curTokenTxt = "";
				continue;
			}
			//sec quoeo
			if(c=='\"' && this.curStat.equals("strEnd"))
			{
				this.curStat = "strStart";
			//	tokens.add(this.curToken);
				this.curTokenTxt = "";
				continue;
			}
			
			
			
			if(c==',' && this.curStat.equals("brkStart"))
			{
				//this.curStat = "strEnd";
				Token tk3=new Token(this.curTokenTxt).setType("var");
				tokens.add(tk3);
				this.curTokenTxt = "";
				continue;
			}
			
			if(c==',' && this.curStat.equals("strEnd"))
			{
			//	tokens.add(","); 
			 	this.curTokenTxt = "";
				continue;
			}
		//	if (this.curStat.equals("ini"))
				curTokenTxt = curTokenTxt + String.valueOf(c);
		}
		return tokens;
	}

	/**
	 * add commaStat
	 * @return
	 */
	@Deprecated
	public List getTokensV2() {
		code_char_arr = code.toCharArray();
		for (char c : code_char_arr) {
			// get next char,,then change stat
			// jude cur char and cur stat...then if or not chage stat
			if (c == '(' && !this.curStat.equals("strStart")) {    //&&  cur stta=ini
				this.curStat = "brkStart";
				Token tk=new Token(this.curTokenTxt).setType("var");
				
				tokens.add(tk);
				
				Token tk2=new Token("(").setType("op");
				tokens.add(tk2);
				this.curTokenTxt = "";
				continue;
			}
//			if(c=='\\')
//			{
//				this.curStat = "splashStart";
//			}

//			if (c == '.' && this.curStat.equals("brkStart")) {
//
//				curToken = curToken + String.valueOf(c);
//				continue;
//
//				// this.curStat.equals("brkEnd"))
//
//			}
//			
			if (c == ')'  && !this.curStat.equals("strStart") ) {    //&& cur stat =brk start
				this.curStat = "brkEnd";
				if(this.curTokenTxt.length()>0)
				{
					Token tk3=new Token(this.curTokenTxt).setType("var");
					tokens.add(tk3);
				}
				
				Token tk2=new Token(")").setType("op");
				tokens.add(tk2);
				this.curTokenTxt = "";
				continue;
			}
			
			if (c == '.' && this.curStat.equals("brkEnd")) {
				 
				Token tk2=new Token(".").setType("var");
				tokens.add(tk2);
				curTokenTxt = "";
				continue;
			}
			
			//---------------str type 
			if(c=='\"' && this.curStat.equals("brkStart"))
			{
				this.curStat = "strStart";
			//	tokens.add(c);
				this.curTokenTxt = "";
				continue;
			}
			
			
			if(c=='\"' && this.curStat.equals("strStart"))
			{
				this.curStat = "strEnd";
				Token tk3=new Token(this.curTokenTxt).setType("str");
				tokens.add(tk3);
				this.curTokenTxt = "";
				continue;
			}
			//sec quoeo
			if(c=='\"' && this.curStat.equals("commaStat"))
			{
				this.curStat = "strStart";
			//	tokens.add(this.curToken);
				this.curTokenTxt = "";
				continue;
			}
			
			
			
			if(c==',' && this.curStat.equals("strEnd"))
			{
				this.curStat = "commaStat";
				Token tk3=new Token( String.valueOf(c)).setType("spltr");
				tokens.add(tk3);
				this.curTokenTxt = "";
				continue;
			}
			
//			if(c==',' && this.curStat.equals("strEnd"))
//			{
//			//	tokens.add(","); 
//			 	this.curTokenTxt = "";
//				continue;
//			}
		//	if (this.curStat.equals("ini"))
				curTokenTxt = curTokenTxt + String.valueOf(c);
		}
		return tokens;
	}

	/**
	 * new (op char),comm (op char) ,, [] feokwahaor,as arr splitor..  
	 * @return
	 */
	public List getTokensV3() {
		code_char_arr = code.toCharArray();
		for (char c : code_char_arr) {
			if(this.curTokenTxt.equals("1598"))
				System.out.println("dbg");
			// get next char,,then change stat
			// jude cur char and cur stat...then if or not chage stat
			if (c == '[' && !this.curStat.equals("strStart"))
			{
				this.curStat="sqBrkStart";
				Token tk2=new Token("[").setType("spltr");
				tokens.add(tk2);
				this.curTokenTxt = "";
				continue;
				
			}
				
		     if (c == ']' && !this.curStat.equals("strStart"))
		     {
		    	 this.curStat="sqBrkEnd";
					Token tk2=new Token("]").setType("spltr");
					tokens.add(tk2);
					this.curTokenTxt = "";
					continue;
		     }
			if(c==' ' && this.curStat.equals("ini"))
			{
				if(this.curTokenTxt.trim().toLowerCase().equals("new"))
				{
					this.curStat = "brkStart";
					Token tk=new Token(this.curTokenTxt).setType("keyword");				
					tokens.add(tk);
					this.curTokenTxt = "";
					continue;
				}
			
			}
			if (c == '(' && !this.curStat.equals("strStart")) {    //&&  cur stta=ini
				this.curStat = "brkStart";
				Token tk=new Token(this.curTokenTxt).setType("var");
				
				tokens.add(tk);
				
				Token tk2=new Token("(").setType("op");
				tokens.add(tk2);
				this.curTokenTxt = "";
				continue;
			}
//			if(c=='\\')
//			{
//				this.curStat = "splashStart";
//			}

//			if (c == '.' && this.curStat.equals("brkStart")) {
//
//				curToken = curToken + String.valueOf(c);
//				continue;
//
//				// this.curStat.equals("brkEnd"))
//
//			}
//			
			
			if (c == ')' && !this.curStat.equals("strStart")) { // && cur stat
																// =brk start

				if (this.curTokenTxt.length()> 0) //jeig cant smp...  last end brk is impt..if smp continue ,then cant add end brk to token
				{

					String type = gettype_4curCharIsBrkend(this.curTokenTxt, this.curStat);
					Token tk3 = new Token(this.curTokenTxt).setType(type);
					tokens.add(tk3);
				}

				Token tk2 = new Token(")").setType("op");
				tokens.add(tk2);
				this.curTokenTxt = "";
				this.curStat = "brkEnd";
				continue;
			}
			
			if (c == '.' && this.curStat.equals("brkEnd")) {
				 
				Token tk2=new Token(".").setType("op");
				tokens.add(tk2);
				curTokenTxt = "";
				continue;
			}
			
			//---------------str type 
			//&&   this.curStat.equals("brkStart")   mayube   []  arr hto..
			//first quoe
			if( (c=='\"'|| c=='\'')  &&   (this.curStat != "strStart"))   //
			{
				this.curStat = "strStart";
			//	tokens.add(c);
				this.curTokenTxt = "";
				continue;
			}
			
			//for close quoue
			if( (c=='\"'|| c=='\'') && this.curStat.equals("strStart"))
			{
				this.curStat = "strEnd";
				Token tk3=new Token(this.curTokenTxt).setType("str");
				tokens.add(tk3);
				this.curTokenTxt = "";
				continue;
			}
			//sec quoeo
//			if(  (c=='\"'|| c=='\'') && this.curStat.equals("commaStat"))
//			{
//				this.curStat = "strStart";
//			//	tokens.add(this.curToken);
//				this.curTokenTxt = "";
//				continue;
//			}
			
			
			
			if(c==',' && !this.curStat.equals("strStart"))
			{
				
				
				if(this.curTokenTxt.trim().length()>0)
			 	{  
						String curTokenTye="con";
						if(this.curTokenTxt.startsWith(":"))
							curTokenTye="op";
						Token tk4=new Token(this.curTokenTxt).setType(curTokenTye);
						tokens.add(tk4);
				 }
				
				Token tk3=new Token( String.valueOf(c)).setType("spltr");
				tokens.add(tk3);
				this.curTokenTxt = "";
				this.curStat = "commaStat";
				continue;
			}
			
//			if(c==',' && this.curStat.equals("strEnd"))
//			{
//			//	tokens.add(","); 
//			 	this.curTokenTxt = "";
//				continue;
//			}
		//	if (this.curStat.equals("ini"))
				curTokenTxt = curTokenTxt + String.valueOf(c);
		}
		return tokens;
	}


	/**
	attilax    2016年10月24日  下午3:40:27
	 * @param curTokenTxt2
	 * @param curStat2
	 * @return
	 */
	private String gettype_4curCharIsBrkend(String curTokenTxt2, String lastStat2) {
		 if(curTokenTxt2.contains("."))
			 return "var";
		 else if(curTokenTxt2.startsWith(":") &&  !lastStat2.equals("strStart"))
			 return "op";
		 else if( lastStat2.equals("colon") )
			 return "op";
			 else if( lastStat2.equals("strEnd"))
				 return "str";
			 else if(lastStat2.equals("comma"))
				 
		return   "con";
		return "con";
	}


	/**
	attilax    2016年10月24日  下午3:34:38
	 * @param curTokenTxt2
	 * @return
	 */
	private String gettype(String curTokenTxt2) {
		 if(curTokenTxt2.contains("."))
			 return "var";
			 else
		return   "con";
	}

	
}
